# encoding=utf8
'''
author Kevin li
date  2017.3.3
'''

from sdktest_module.utils.tcp_client import TcpClient
import json
from sdktest_module.multiTest.callback_buffer import CallBackBuffer
from sdktest_module.multiTest.return_buffer import ReturnBuffer
from sdktest_module.multiTest.error_buffer import ErrorBuffer
import datetime

def check_null(origin_func):
    # @wrapper(origin_func) # 加上报错：UnboundLocalError: local variable 'wrapper' referenced before assignment
    def wrapper(self, *args, **kwargs):
        if not self.device_id:
            print("Warning: device_id is none， return!!!")
            return None
        return origin_func(self, *args, **kwargs)
    return wrapper


class Driver:
    def __init__(self, device, role, rpc_ip, rpc_port):
        self.role = role
        self.device = device
        self.device_id = device.device_id if device else None
        self.port = 9000
        self.rpc_ip = rpc_ip
        self.rpc_port = rpc_port
        self.host_port = device.client_port
        self.tcpclient = TcpClient(server_ip=rpc_ip,
                                   server_port=rpc_port,
                                   data_handler=self.dataHandler,
                                   err_handler=self.errHandler,
                                   device_info=self.__str__(),
                                   connect_status_handler=self.connectStatusHandler)
        self.callback_buf = CallBackBuffer(role)
        self.return_buf = ReturnBuffer()
        self.error_buf = ErrorBuffer(role)
        self.tcp_error = False

    def __str__(self):
        return '{}(brand:{}, udid:{}, id:{})'.format(self.role,
                                                     self.device.brand,
                                                     self.device.serial,
                                                     self.device.device_id)

    def initialize(self):
        """
        初始化 1：adb forward; 2.start watcher处理弹窗,子类实现
        """

    @check_null
    def connect(self):
        self.tcpclient.connect()

    @check_null
    def disconnect(self):
        self.tcpclient.disconnect()

    @check_null
    def stop_app(self):
        '''子类实现'''
        pass

    @check_null
    def start_app(self):
        '''子类实现'''
        pass

    @check_null
    def install_app(self, url):
        '''子类实现'''
        pass

    @check_null
    def finish(self):
        '''子类实现'''
        pass

    def send_command(self, *cmds, wait_return=True, check_empty=True):
        print("[{}] {} send command:{}".format(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f'), self.__str__(), cmds))

        if check_empty:
            self.callback_buf.check_empty()
        self.callback_buf.clear()
        self.return_buf.clear()
        if len(cmds) > 1:
            self.tcpclient.send_msg(str(list(cmds)))
        else:
            self.tcpclient.send_msg(str(cmds[0]))
        if wait_return:
            for cmd in cmds:
                dic = eval(cmd)
                self.return_buf.wait_return(dic['api'])
                # 检查是否收到错误信息
                self.error_buf.constains_error()

    def dataHandler(self, data):
        print("[{}] {} receiv server msg:{}".format(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f'), self.__str__(), data).replace('\n', ''))
        try:
            if 'Cmd' in data:
                return
            dics = json.loads(data)
            if dics['type'] == 'callback':
                self.callback_buf.store_callback(dics['key'], dics['value'])
            elif dics['type'] == 'return':
                self.return_buf.store_return(dics['key'], dics['value'])
            elif dics['type'] == 'error':
                # 若在这里断言会导致监听回调的子线程退出
                self.error_buf.store_error(dics['key'], dics['value'])
        except json.JSONDecodeError:
            print('json loads error:'+data)


    def errHandler(self, message):
        print("{} Tcp client error occurs:{}".format(self.__str__(), message))
        self.tcp_error = True

    def connectStatusHandler(self, error):
        self.tcp_error = error

    def clear(self):
        """
        清理消息
        """
        self.callback_buf.clear()
        self.return_buf.clear()

    def _print_log(self, log):
        print('{} {}'.format(self.__str__(), log))


